#include "main.h"
void InputManager::getInput() {
    cout << "\n******************************************" << endl;
    cout << "*          Buck-Boost Converter Tool    *" << endl;
    cout << "******************************************" << endl;

    cout << "Step 1: Enter input voltage in V: ";
    cin >> Vin;

    cout << "Step 2: Enter output voltage in V: ";
    cin >> Vout;

    cout << "Optional Inputs (Press 0 to skip any optional input):" << endl;

    cout << "- Enter max ripple voltage (in V): ";
    cin >> rippleVoltage;

    cout << "- Enter max ripple current (in A): ";
    cin >> rippleCurrent;

    cout << "- Enter input voltage frequency (in Hz): ";
    cin >> frequency;

    cout << "- Enter output load resistance (in Ohm): ";
    cin >> loadR;
    
    cout << "\nAll parameters saved successfully!" << endl;
}



bool InputManager::validateInput() {
    bool isValid = true;

    if (Vin <= 0) {
        cout << "Error: Input voltage (Vin) must be greater than 0." << endl;
        isValid = false;
    }

    if (Vout <= 0) {
        cout << "Error: Output voltage (Vout) must be greater than 0." << endl;
        isValid = false;
    }

    if (rippleVoltage < 0) {
        cout << "Error: Ripple voltage must be non-negative." << endl;
        isValid = false;
    }

    if (rippleCurrent < 0) {
        cout << "Error: Ripple current must be non-negative." << endl;
        isValid = false;
    }

    if (frequency < 0) {
        cout << "Error: Frequency must be non-negative." << endl;
        isValid = false;
    }

    if (loadR < 0) {
        cout << "Error: The resistance must be non-negative." << endl;
        isValid = false;
    }

    return isValid;
}



string Calculator::determineMode() {
    return (Vout > Vin) ? "Boost" : "Buck";
}

void Calculator::calculateBoost() {
    dutyCycle = 1 - (Vin / Vout);

    if (frequency > 0 && rippleCurrent > 0) {
        inductance = (Vin * dutyCycle) / (frequency * rippleCurrent);
    } else {
        inductance = 0;
    }

    if (frequency > 0 && rippleVoltage > 0 && loadR>0) {
        capacitance = (Vout / rippleVoltage) * (dutyCycle/(loadR*frequency));
    } else {
        capacitance = 0;
    }
}

void Calculator::calculateBuck() {
    dutyCycle = Vout / Vin;

    if (frequency > 0 && rippleCurrent > 0) {
        inductance = (Vin - Vout)*dutyCycle / (frequency * rippleCurrent);
    } else {
        inductance = 0;
    }

    if (frequency > 0 && rippleVoltage > 0) {
        capacitance = rippleCurrent / (rippleVoltage * frequency*8);
    } else {
        capacitance = 0;
    }
}

void ResultManager::displayResults(const string& mode) {
    cout << "******************************************" << endl;
    cout << "*            Calculation Results         *" << endl;
    cout << "******************************************" << endl;
    cout << "------------------------------------------" << endl;
    cout << "Mode: " << mode << endl;
    cout << "Input Parameters:" << endl;
    cout << "Vin: " << Vin << " V, Vout: " << Vout << " V" << endl;
    if (rippleVoltage > 0) cout << "Max Ripple Voltage: " << rippleVoltage << " V" << endl;
    if (rippleCurrent > 0) cout << "Max Ripple Current: " << rippleCurrent << " A" << endl;
    if (frequency > 0) cout << "Frequency: " << frequency << " Hz" << endl;

    cout << "\nCalculation Results:" << endl;
    cout << "- Duty Cycle: " << dutyCycle << endl;
    if (inductance > 0) {
        cout << "- Inductance: " << inductance << " H" << endl;
    } else {
        cout << "- Inductance: Skipped (missing parameters)" << endl;
    }
    if (capacitance > 0) {
        cout << "- Capacitance: " << capacitance << " F" << endl;
    } else {
        cout << "- Capacitance: Skipped (missing parameters)" << endl;
    }
    cout << "------------------------------------------" << endl;

    saveResultsToCSV(mode);
}

void ResultManager::saveResultsToCSV(const string& mode) {
    ofstream file;
    file.open("calculation_results.csv", ios::app);

    if (file.is_open()) {
        if (file.tellp() == 0) {
            file << "Mode,Vin,Vout,RippleVoltage,RippleCurrent,Frequency,LoadR,DutyCycle,Inductance,Capacitance\n";
        }

        file << mode << ","
             << Vin << ","
             << Vout << ","
             << rippleVoltage << ","
             << rippleCurrent << ","
             << frequency << ","
             << loadR << ","
             << dutyCycle << ","
             << inductance << ","
             << capacitance << "\n";

        cout << "Results saved to 'calculation_results.csv'." << endl;
    } else {
        cout << "Error: Unable to open file for saving results." << endl;
    }

    file.close();
}

void ResultManager::displayLastResults() {
    ifstream file("calculation_results.csv");

    if (!file.is_open()) {
        cout << "Error: Unable to open file for reading results." << endl;
        return;
    }

    vector<string> lines;
    string line;

    while (getline(file, line)) {
        lines.push_back(line);
    }

    file.close();

    if (lines.size() <= 1) {
        cout << "No previous results found." << endl;
        return;
    }

    string lastLine = lines.back();

    stringstream ss(lastLine);
    string mode, vin, vout, rippleCurrent, rippleVoltage, frequency, loadR, dutyCycle, inductance, capacitance;

    // Read values from the CSV line
    getline(ss, mode, ',');
    getline(ss, vin, ',');
    getline(ss, vout, ',');
    getline(ss, rippleCurrent, ',');
    getline(ss, rippleVoltage, ',');
    getline(ss, frequency, ',');
    getline(ss, loadR, ',');
    getline(ss, dutyCycle, ',');
    getline(ss, inductance, ',');
    getline(ss, capacitance, ',');

    // Display the results
    cout << "******************************************" << endl;
    cout << "*         Last Calculation Results      *" << endl;
    cout << "******************************************" << endl;
    cout << "Mode: " << mode << endl;
    cout << "Vin: " << vin << " V, Vout: " << vout << " V" << endl;
    cout << "Ripple Current: " << rippleCurrent << " A, Ripple Voltage: " << rippleVoltage << " V" << endl;
    cout << "Frequency: " << frequency << " Hz, Load Resistance: " << loadR << " Ohm" << endl;
    cout << "Duty Cycle: " << dutyCycle << endl;
    cout << "Inductance: " << inductance << " H" << endl;
    cout << "Capacitance: " << capacitance << " F" << endl;
    cout << "******************************************" << endl;
}

void showLoadingEffect(int repeatCount) {
    for (int i = 0; i < repeatCount; ++i) {
        cout << "\rProcessing"; 
        for (int j = 0; j <= i % 5; ++j) {
            cout << "."; 
        }
        cout.flush(); 
        this_thread::sleep_for(chrono::milliseconds(500)); 
    }
    cout << endl; 
    cout << "\033c";
}

void show_new_cal(int repeatCount) {
    for (int i = 0; i < repeatCount; ++i) {
        cout << "\rStarting a new calculation"; 
        for (int j = 0; j <= i % 5; ++j) {
            cout << "."; 
        }
        cout.flush();
        this_thread::sleep_for(chrono::milliseconds(500)); 
    }
    cout << endl; 
    cout << "\033c";
}


void promptRestart() {
    cout << "\nPress Enter to restart..." << endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cin.get();
    cout << "Restarting..." << endl;
}

void displayMenu() {
    int choice;
    string mode;
    ResultManager result;
    bool hasResults = false;

    do {
        showLoadingEffect(5);
        cout << "\n******************************************" << endl;
        cout << "*          Buck-Boost Converter Tool     *" << endl;
        cout << "******************************************" << endl;
        cout << "1. Start a New Calculation" << endl;
        cout << "2. View Last Calculation Results" << endl;
        cout << "3. Exit" << endl;
        cout << "Enter your choice: ";
        cin >> choice;
        if (cin.fail() || choice < 1 || choice > 3) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Invalid choice. Please enter a number between 1 and 3.\n";
            promptRestart();
            continue;
        }

        switch (choice) {
            case 1: {
                show_new_cal(5);
                result.getInput();
                showLoadingEffect(5);

                if (!result.validateInput()) {
                    cout << "Invalid input parameters. Please try again.\n";
                    hasResults = false;
                    promptRestart();
                    break;
                }

                mode = result.determineMode();
                if (mode == "Boost") {
                    result.calculateBoost();
                } else if (mode == "Buck") {
                    result.calculateBuck();
                }

                result.displayResults(mode);
                hasResults = true;
                promptRestart();
                break;
            }

            case 2: {
                if (hasResults) {
                    cout << "\nDisplaying the last calculation results...\n";
                    result.displayLastResults();
                } else {
                    cout << "No previous valid results found. Please perform a calculation first.\n";
                }
                promptRestart();
                break;
            }

            case 3:
                cout << "Exiting the program. Goodbye!\n";
                break;

            default:
                cout << "Invalid choice. Please try again.\n";
                break;
        }

    } while (choice != 3);
}
